include( "powers/_base.lua" );

heroes.Powers = heroes.Powers or { };
heroes.PowerHooks = { };

heroes.PowerSetDelay = 3;

function heroes.Initialize( )
	
	local files = file.FindInLua( "powers/pow_*.lua" );
	
	for _, filename in pairs( files ) do
		
		POWER = heroes.CreatePower( filename );
			
			include( "powers/"..filename );
			
			POWER.Id = table.insert( heroes.Powers, POWER );
			
			POWER:Initialize( );
			
		POWER = nil;
		
	end
	
end
hook.Add( "Initialize", "heroes.Initialize", heroes.Initialize );

function heroes.PlayerInitialSpawn( pl )
	
	umsg.Start( "SetupHeroes", pl );
		umsg.Bool( true );
	umsg.End( );
	
	for _, power in pairs( heroes.Powers ) do
		
		umsg.Start( "AddPwr", pl );
			umsg.String( power.Name );
			umsg.String( power.Desc );
			umsg.Short( power.Id );
		umsg.End( );
		
	end
	
	heroes.SetPower( pl, -1 );
	
	pl.NextPowerSet = CurTime( ) + 1;
	
end
hook.Add( "PlayerInitialSpawn", "hook.PlayerInitialSpawn", heroes.PlayerInitialSpawn );

//BECAUSE I LIKE BIG LOOPS LOL
function heroes.GetPower( name )
	
	if name then
		
		if type( name ) == "number" then
			
			return heroes.Powers[ name ];
			
		end
		
		if name:sub( -4 ) == ".lua" then
			
			name = name:match( "^pow_([%w_]+)%.lua$");
			
		end
		
		if name then
			
			for _, power in pairs( heroes.Powers ) do
				
				if power.UniName == name then
					
					return power;
					
				end
				
			end
			
		end
		
	end
	
end

function heroes.GetPlPower( pl )
	
	return heroes.GetPower( pl.PowerId );
	
end

//LOL NOES! NO NW VARS???
function heroes.SetPower( pl, pow )
	
	local oldid = pl.PowerId;
	
	//we run this function to set the power for the first time, so don't call Disabled then
	if oldid then
		
		heroes.CallHook( oldid, "Disabled", pl );		
		
	end
	
	pl.PowerId = pow;
	
	umsg.Start( "SetPwr", RecipientFilter( ):AddAllPlayers( ) );
		umsg.Entity( pl );
		umsg.Short( pow );
	umsg.End( );
	
	if pow != -1 then
		
		heroes.CallHook( pow, "Enabled", pl );
		
	end
	
end

function heroes.CallHook( pow, name, pl, ... )
	
	local power = heroes.GetPower( pow );
	
	if power && pl.PowerId == power.Id then
		
		local func = power[ name ];
		
		if type( func ) == "function" then
			
			power.Owner = pl;
				
				//can't return here, else we'd have 'shadow owners'
				func( power, ... );
				
			power.Owner = nil;
			
		end
		
	end
	
end

function heroes.CC_SetPower( pl, cmd, args )
	
	local id = tonumber( args[ 1 ] );
	
	if id && pl.NextPowerSet < CurTime( ) then
		
		heroes.SetPower( pl, id );
		
		pl.NextPowerSet = CurTime( ) + heroes.PowerSetDelay;
		
	end
	
end
concommand.Add( "heroes_set_power", heroes.CC_SetPower );

function heroes.ReloadPowers( )
	
	for _, pl in pairs( player.GetAll( ) ) do
		
		heroes.SetPower( pl, -1 );
		
	end

	heroes.Powers = { };
	
	heroes.Initialize( );
	
	print( "Reloaded "..#heroes.Powers.." powers.." );
	
end
concommand.Add( "heroes_reload", heroes.ReloadPowers );

function heroes.DumpPowers( )
	
	print( ("-"):rep( 50 ) );
	
	for _, power in pairs( heroes.Powers ) do
		
		print( "Name: "..power.Name );
		print( "Desc: "..power.Desc );
		print( "Version: "..power.Version );
		print( "Author: "..power.Author );
		print( "---" );
		print( "Id: "..power.Id );
		print( "UniName: "..power.UniName );
		
		print( ("-"):rep( 50 ) );
		
	end
	
end
concommand.Add( "heroes_dump", heroes.DumpPowers );

function heroes.PowerHooks.KeyPress( pl, key )
	
	heroes.CallHook( pl.PowerId, "KeyPress", pl, key );
	
end
hook.Add( "KeyPress", "PowerHooks.KeyPress", heroes.PowerHooks.KeyPress );

function heroes.PowerHooks.KeyRelease( pl, key )
	
	heroes.CallHook( pl.PowerId, "KeyRelease", pl, key );
	
end
hook.Add( "KeyRelease", "PowerHooks.KeyRelease", heroes.PowerHooks.KeyRelease );

function heroes.PowerHooks.Think( )
	
	for _, pl in pairs( player.GetAll( ) ) do
		
		local power = heroes.GetPower( pl.PowerId );
		
		if power && CurTime( ) > power._NextThink then
			
			heroes.CallHook( pl.PowerId, "Think", pl );
			
		end
		
	end
	
end
hook.Add( "Think", "PowerHooks.Think", heroes.PowerHooks.Think );

function heroes.PowerHooks.ScalePlayerDamage( pl, hitgroup, dmg )
	
	heroes.CallHook( pl.PowerId, "ScalePlayerDamage", pl, hitgroup, dmg );
	
end
hook.Add( "ScalePlayerDamage", "PowerHooks.ScalePlayerDamage", heroes.PowerHooks.ScalePlayerDamage );